/**
 *******************************************************************************
 * @FileName  : usb_debug.h
 * @Author    : GaoQiu
 * @CreateDate: 2021-5-15
 * @Copyright : Copyright(C) GaoQiu
 *              All Rights Reserved.
 *******************************************************************************
 *
 * The information contained herein is confidential and proprietary property of
 * GaoQiu and is available under the terms of Commercial License Agreement
 * between GaoQiu and the licensee in separate contract or the terms described
 * here-in.
 *
 * This heading MUST NOT be removed from this file.
 *
 * Licensees are granted free, non-transferable use of the information in this
 * file under Mutual Non-Disclosure Agreement. NO WARRENTY of ANY KIND is provided.
 *
 *******************************************************************************
 */

#include "usb_debug.h"
#include "usb_config.h"
#include <stdarg.h>

#include "utils/assert.h"
#include "utils/byte_stream.h"

UsbDbgCb_t usbDbgCb;

#if !USE_DBG_USE_DYNAMIC_MEM
static uint8_t usbDbgBuf[(4+USB_DBG_BUF_SIZE) * USB_DBG_BUF_NUM] = {0};
#endif

void USB_DebugInit(void)
{
	fifo_t *pFifo = &usbDbgCb.txFifo;

#if !USE_DBG_USE_DYNAMIC_MEM
	uint32_t size = 4 + USB_DBG_BUF_SIZE;
	uint32_t num  = USB_DBG_BUF_NUM;

	uint8_t res = FIFO_Init(pFifo, usbDbgBuf, size, num);
	ASSERT(res == FIFO_SUCCESS, USB_ERR_DBG_FIFO_ALLOC_FAILED|res);
#else
	uint32_t size = 4 + USB_DBG_BUF_SIZE;
	uint32_t num  = USB_DBG_BUF_NUM;

	uint8_t *pAvailMem = HeapAllocEx(size * num);
	ASSERT(pAvailMem != NULL, USB_ERR_DBG_FIFO_ALLOC_FAILED);

	uint8_t res = FIFO_Init(pFifo, pAvailMem, size, num);
	ASSERT(res == FIFO_SUCCESS, USB_ERR_DBG_FIFO_ALLOC_FAILED|res);
#endif
}

void USB_Print(const char *format, ...)
{
	va_list va;
	va_start(va, format);

	fifo_t *pFifo = &usbDbgCb.txFifo;
	if(FIFO_IsFull(pFifo)){
		return;//have buffer available
	}

	uint8_t *pBuf = FIFO_GetWriteBuf(pFifo);
	uint8_t *p = pBuf + 2;       //skip length field

	uint32_t len = PrintVsn((char*)p, pFifo->size - 3, format, va);

	UINT16_TO_BSTREAM(pBuf, len);//add length field
	FIFO_MoveToNextWriteBuf(pFifo);

	va_end(va);
}

void USB_PrintData(uint8_t *pData, uint16_t len)
{
#if 1
	fifo_t *pFifo = &usbDbgCb.txFifo;
	if(FIFO_IsFull(pFifo)){
		return;
	}

	uint8_t *pBuf = FIFO_GetWriteBuf(pFifo);
	uint8_t *p = pBuf + 2; //skip length field

	uint32_t cnt = TrackHexToString((char*)p, pFifo->size - 4, pData, len);
	//if(cnt){
		p[cnt++] = '\r';
		p[cnt++] = '\n';
	//}

	UINT16_TO_BSTREAM(pBuf, cnt);//add length field
	FIFO_MoveToNextWriteBuf(pFifo);
#else
	uint8_t *p = pData;

	while(len > 0)
	{
		uint32_t fragLen = len > 16 ? 16:len;
		char buf2[256] = {0};

		int cnt = TrackHexToString(buf2, sizeof(buf2)-1, p, fragLen);
		buf2[cnt] = 0;
		USB_Print("\t%s\r\n", buf2);

		len -= fragLen;
		p += fragLen;
	}
#endif
}

void USB_PrintStringAndData(const char *pDesc, uint8_t *pData, uint16_t len)
{
	fifo_t *pFifo = &usbDbgCb.txFifo;
	if(FIFO_IsFull(pFifo)){
		return;
	}

	uint8_t *pBuf = FIFO_GetWriteBuf(pFifo);
	uint8_t *p = pBuf + 2; //skip length field

	uint32_t cnt = strlen(pDesc);
	if(pDesc != NULL){
		memcpy(p, pDesc, cnt);
	}
	cnt += TrackHexToString((char*)(p+cnt), pFifo->size - 3 - cnt , pData, len);
	if(cnt){
		p[cnt++] = '\n';
	}
	UINT16_TO_BSTREAM(pBuf, cnt);//add length field
	FIFO_MoveToNextWriteBuf(pFifo);
}
